using GroupSix.Domain.Events;
using GroupSix.Domain.Services;
using GroupSix.Domain.ValueObjects;

namespace GroupSix.Domain.Entity.App;

public class GsUser : EntityBase
{
    private readonly List<IDomainEvent> _domainEvents = new();
    
    public string Username { get; private set; } = null!;
    public string PasswordHash { get;private  set; } = null!;
    public string? Salt { get; private set; }

    public string? Nickname { get; set; } 
    public string Email { get; set; } = null!;
    public string? Phone { get; set; }
    public string? Avatar { get; set; }

    public int Status { get; private set; } = 1; //状态
    
    public int LoginFailCount { get; private set; } = 0; //登录失败次数
    public DateTime? LockoutEndTime { get; private set; } //锁定结束时间
    
    public ICollection<GsUserRole> GsUserRole { get; private set; } = new List<GsUserRole>();

    private GsUser() { }

    public GsUser(
        string username,
        string passwordHash,
        string? salt,
        string email,
        string? phone,
        string? nickname,
        string? avatar,
        int status )
    {
        Username = username;
        PasswordHash = passwordHash;
        Salt = salt;
        Email = email;
        Phone = phone;
        Nickname = nickname;
        Avatar = avatar;
        Status = status;
        
        // 分发用户注册成功事件
        _domainEvents.Add(new UserRegisteredEvent(Id, Username, Email));
    }

    public void UpdateContact(string email, string? phone)
    {
        Email = email;
        Phone = phone;
        UpdatedAt = DateTime.Now;
    }

    public void UpdateProfile(string? nickname, string? avatar)
    {
        Nickname = nickname;
        Avatar = avatar;
        UpdatedAt = DateTime.Now;
    }

    public void ChangePassword(string newPasswordHash, string? newSalt = null)
    {
        PasswordHash = newPasswordHash;
        Salt = newSalt;
        UpdatedAt = DateTime.Now;
    }

    public void ChangeStatus(int newStatus)
    {
        Status = newStatus;
        UpdatedAt = DateTime.Now;
    }

    public void UpdateNickname(string? nickname)
    {
        Nickname = nickname;
        UpdatedAt = DateTime.Now;
    }

    public void UpdateEmail(string email)
    {
        Email = email;
        UpdatedAt = DateTime.Now;
    }

    public void UpdatePhone(string? phone)
    {
        Phone = phone;
        UpdatedAt = DateTime.Now;
    }

    public void UpdateAvatar(string? avatar)
    {
        Avatar = avatar;
        UpdatedAt = DateTime.Now;
    }

    public void IncrementLoginFailCount()
    {
        LoginFailCount++;
        UpdatedAt = DateTime.Now;
    }

    public void ResetLoginFailCount()
    {
        LoginFailCount = 0;
        LockoutEndTime = null;
        UpdatedAt = DateTime.Now;
    }

    public void SetLockoutEndTime(DateTime? lockoutEndTime)
    {
        LockoutEndTime = lockoutEndTime;
        UpdatedAt = DateTime.Now;
    }

    /// <summary>
    /// 尝试登录
    /// </summary>
    /// <param name="password">密码</param>
    /// <param name="passwordHasher">密码哈希服务</param>
    /// <returns>登录结果</returns>
    public LoginResult TryLogin(string password, IPasswordHasher passwordHasher)
    {
        // 检查是否锁定
        if (LockoutEndTime != null && LockoutEndTime > DateTime.Now)
        {
            return LoginResult.Locked(LockoutEndTime.Value);
        }

        // 验证密码
        var hash = passwordHasher.HashPassword(password, Salt ?? "");
        if (PasswordHash != hash)
        {
            IncrementLoginFailCount();
            
            // 如果失败次数达到5次，锁定账户
            if (LoginFailCount >= 5)
            {
                var lockoutEndTime = DateTime.Now.AddMinutes(30);
                SetLockoutEndTime(lockoutEndTime);
                _domainEvents.Add(new UserAccountLockedEvent(Id, Username, lockoutEndTime));
            }
            
            _domainEvents.Add(new UserLoginFailedEvent(Username, LoginFailCount));
            return LoginResult.Failed(LoginFailCount);
        }

        // 登录成功
        ResetLoginFailCount();
        _domainEvents.Add(new UserLoginSucceededEvent(Id, Username));
        return LoginResult.Success();
    }

    /// <summary>
    /// 获取领域事件
    /// </summary>
    /// <returns>领域事件列表</returns>
    public IReadOnlyCollection<IDomainEvent> GetDomainEvents()
    {
        return _domainEvents.AsReadOnly();
    }

    /// <summary>
    /// 清除领域事件
    /// </summary>
    public void ClearDomainEvents()
    {
        _domainEvents.Clear();
    }
}